package com.omnisyr.textrebuilder;

import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.ImageIO;

import com.omnisyr.textrebuilder.common.Color;
import com.omnisyr.textrebuilder.common.ColorPointCloud;
import com.omnisyr.textrebuilder.common.Palette;
import com.omnisyr.textrebuilder.util.Counter;
import com.omnisyr.textrebuilder.util.CounterNode;
import com.omnisyr.textrebuilder.util.structure.SimpleTreeMap;

public class PointCloudAnlayzer {

	/**
	 * Use CPU export the palette of an image. </BR>
	 * And the first step and the last step of color dense will be exported. </BR>
	 * </BR>
	 * Example: </BR>
	 * </BR>
	 * file: "xxx.jpg" </BR>
	 * mode: true </BR>
	 * </BR>
	 * as output => </BR>
	 * A "palette.png" file. </BR>
	 * A "dense_first.csv" file. </BR>
	 * A "dense_last.csv" file. </BR>
	 * </BR>
	 * PNG file can be exhibited directly. </BR>
	 * CSV files can be turned into PLY files for being exhibited. </BR>
	 * 
	 * 
	 * 
	 * @param file </BR>
	 *             input file </BR>
	 * @param mode </BR>
	 *             true for average pooling </BR>
	 *             false for max pooling </BR>
	 */
	private static void read(File file, boolean mode) {

		try {

			Counter<Color> counter = new Counter<Color>(Color.hashComparator);
			ColorPointCloud cloud = new ColorPointCloud();
			BufferedImage image = ImageIO.read(file);

			int ave = 0;
			int lastAve = 0;

			for (int i = 0; i < image.getWidth(); i++) {

				for (int j = 0; j < image.getHeight(); j++) {

					Color color = new Color(image.getRGB(i, j));

					if (color.isGray()) {

						continue;

					}

					cloud.add(color);
					counter.add(color);

				}

			}

			while (true) {

				ave = cloud.buildDenseList(mode);

				saveAsCSV(cloud, "dense_first");

				System.err.println("Average Amount: " + ave);
				System.err.println("----------------------------------------------------------------------------");

				if (ave <= lastAve) {

					break;

				}

				lastAve = ave;

				for (int i = 0; i < 256; i++) {

					for (int j = 0; j < 256; j++) {

						for (int k = 0; k < 256; k++) {

							if (cloud.dense(i, j, k) < ave) {

								cloud.remove(i, j, k);

							}

						}

					}

				}

			}

			counter.build();

			if (counter.get(0) == null) {

				return;

			}

			Palette palette = new Palette();

			SimpleTreeMap<Color, Integer> cache = new SimpleTreeMap<Color, Integer>(Color.hashComparator);

			for (int i = 0; i < 256; i++) {

				for (int j = 0; j < 256; j++) {

					for (int k = 0; k < 256; k++) {

						if (cloud.dense(i, j, k) == 0) {

							continue;

						}

						for (CounterNode<Color> node : counter) {

							Color color = new Color(i, j, k);

							if (Color.getLoss(node.get(), color) < 15) {

								if (cache.get(node.get()) != null) {

									break;

								}

								palette.append(node.get());
								cache.add(node.get(), 0);

								break;

							}

						}

					}

				}

			}

			saveAsCSV(cloud, "dense_last");
			palette.saveAs(new File("palette.png"));

		} catch (Exception ex) {

			ex.printStackTrace();

		}

	}

	private static void saveAsCSV(ColorPointCloud cloud, String name) {

		Palette palette = new Palette();

		for (int i = 0; i < 256; i++) {

			for (int j = 0; j < 256; j++) {

				for (int k = 0; k < 256; k++) {

					if (cloud.dense(i, j, k) > 0) {

						palette.append(new Color(i, j, k));

					}

				}

			}

		}

		palette.saveAs(new File(name + ".csv"));

	}

	// For testing.
	public static void main(String[] args) {

		File[] files = new File("images").listFiles();

		for (File file : files) {

			read(file, true);

		}

	}

}
